import Base from '@/common/cmdBase/cmdBase';
import { EntSelect } from './EntSelect';
import { EntityInfo, EntityPartType, THREE } from '@amcax/web-render';
import { EntOtpMod, PickStatus, SelectType, TabsType } from './type';
import { userEvents } from 'nextcae-base';
import { ToolBarEvents } from '@/components/CmdBar/CmdBottomBtn/type';
import { PickSelect } from './PickSelect';
import { labelManager } from '@/common/preview';
export default class PickManager extends Base {
  public selectType: SelectType = SelectType.ENT; // 选择类型;
  public tabsType: TabsType = TabsType.Geometry; // 是否是几何实体或者网格实体
  static instance: PickManager;
  // ---------- 选择器 -------------------
  private _pickSelect: PickSelect; // 选择器
  private _entSelect: EntSelect; // 实体选择器
  // --------- cmdPickType -------------------
  public cmdPickType = null; // cmd命令实体拾取类型
  public focusPickType = null; // focus 聚焦类型
  public pickStatus: PickStatus;
  public cmdIsCall: boolean = false; // cmd命令是否被调起
  public bottomPickIsCall: boolean = false; // 底部pick命令是否被调起
  static getInstance(): PickManager {
    if (!this.instance) {
      this.instance = new PickManager();
    }
    return this.instance;
  }
  get banHoverEnt(): EntityInfo[] {
    if (this.isCmd) {
      return this._pickSelect.banShiftPickEnts;
    } else {
      return [];
    }
  } // 禁止hover和选中的实体
  get shift() {
    return this._pickSelect.shift;
  }
  get pickMode() {
    return this._pickSelect.getPickMode();
  }
  get isPick() {
    return this.pickStatus === 'pick' && this.pickMode;
  }
  get isCmd() {
    return this.pickStatus === 'cmd' && this.cmdPickType;
  }
  get isFocus() {
    return this.pickStatus === 'focus' && this.focusPickType;
  }
  get pickIsCall() {
    // cmd命令被调起、聚焦命令被调起、底部pick命令被调起
    return this.cmdIsCall || this.isFocus || this.bottomPickIsCall;
  }
  get currentPickType() {
    switch (this.pickStatus) {
      case 'pick':
        return this.pickMode;
      case 'cmd':
        return this.cmdPickType;
      case 'focus':
        return this.focusPickType;
      default: {
        return null;
      }
    }
  }
  constructor() {
    super();
    this._pickSelect = new PickSelect(this);
    this._entSelect = new EntSelect(this);
  }
  optionChange() {
    if (this.selectType === SelectType.ENT) {
      this._entSelect.setHitAndPickType();
    }
  }
  // 设置cmd弹框的拾取类型
  setCmdPickType(value: EntityPartType) {
    this.cmdPickType = value;
    this.optionChange();
  }
  // 设置聚焦拾取类型
  setFocusPickType(value: EntityPartType) {
    this.focusPickType = value;
    this.optionChange();
  }
  // 设置拾取状态， pick 拾取， cmd 弹框拾取
  setPickStatus(value: PickStatus) {
    this.pickStatus = value;
    value === 'cmd' && (this.cmdIsCall = true);
    if (value === 'pick') {
      this._pickSelect.setPickMode();
      this.bottomPickIsCall = true;
    } else {
      this.bottomPickIsCall = false;
    }
    pickManager().optionChange(); // 选择器类型改变
    userEvents.emit(ToolBarEvents.FIRST_BTM_SELECTED);
    this.enablePick = true;
  }
  setSelectType(value: SelectType) {
    this.selectType = value;
    this.optionChange();
  }
  makeId(e: EntityInfo) {
    return Base.makeId(e);
  }
  isEntEqual = (a: EntityInfo, b: EntityInfo) => {
    if (!a || !b) {
      return false;
    }
    return a.idx === b.idx && a.type === b.type && a.dxid === b.dxid;
  };
  // pick
  getPickSelect(): PickSelect {
    return this._pickSelect;
  }
  // 实体选择器
  getEntSelect(): EntSelect {
    return this._entSelect;
  }

  setColor(color: { [key in EntityPartType]?: number }) {
    if (color) {
      this.interactionMgr.selectedColor = color;
    }
  }
  resetSelectedColor() {
    this.interactionMgr.resetSelectedColor();
  }
  onBeforeHovered = (e: EntityInfo, shift?: boolean) => {
    let canHover = !this.getPickSelect().selectedEntMap.has(this.makeId(e));
    if (this.selectType === SelectType.ENT) {
      const flag = this._entSelect.onBeforeHovered(e, shift);
      shift ? flag && (canHover = false) : flag && (canHover = false);
    }
    return shift ? !canHover : canHover;
  };
  handle = (
    e: EntityInfo,
    state = true,
    key = EntOtpMod.SELECTED,
    shift = false,
  ) => {
    if (!e) return null;
    let result = null;
    if (this.selectType === SelectType.ENT) {
      result = this._entSelect.handle(e, state, key, shift);
    }
    return result;
  };
  onMouseLeft = (e: EntityInfo, selected: boolean) => {
    if (this.selectType === SelectType.ENT) {
      return this._entSelect.onMouseDown(e, selected);
    }
    return null;
  };
  setTabsType(value: TabsType) {
    this.tabsType = value;
    if (this.tabsType === TabsType.Element) {
      this.interactionMgr.bindToEntityManager(this.geometryMgr, this.meshMgr);
    } else {
      this.interactionMgr.bindToEntityManager(this.geometryMgr);
    }
    this._pickSelect.setPickMode();
  }
  setUpdataLabel(
    e: EntityInfo,
    label: string = 'FACE: ' + e?.dxid + '_' + e?.idx,
  ) {
    if (this.isPick && !this.shift) {
      if (!labelManager().getCSS2DLabel()) {
        labelManager().setCss2dLabel(label, new THREE.Vector3(...e.point));
        labelManager().setCss2dOffset();
      } else {
        labelManager().setCss2dLabel(label, new THREE.Vector3(...e.point));
      }
    }
  }
  changeSelectEnt(state: 'add' | 'remove', value: EntityInfo | EntityInfo[]) {
    const key = 'selectEnt';
    if (value) {
      if (Array.isArray(value)) {
        value.forEach((item) => {
          this.changeSelectEnt(state, item);
        });
      } else {
        state === 'add'
          ? (this[key][this.makeId(value)] = value)
          : delete this[key][this.makeId(value)];
      }
    } else {
      state === 'remove' && (this[key] = {});
    }
  }
  /**
   * 处理实体的选中或悬停操作。
   * 根据传入的操作模式（选中或悬停），对实体进行相应的添加、移除操作，并更新实体的状态。
   * @param ent - 实体信息对象，包含实体的相关信息。
   * @param state - 表示实体是否处于选中或悬停状态，`true` 表示是，`false` 表示否。
   * @param key - 实体操作模式，指定是悬停操作（`EntOtpMod.HOVER`）还是选中操作（`EntOtpMod.SELECTED`）。
   */
  public hoverSelected(ent: EntityInfo, state: boolean, key: EntOtpMod) {
    const mid = this.getPickSelect().getMid(ent);
    if (key === EntOtpMod.SELECTED && ent.type === this.currentPickType) {
      this.setSelectOrHover(ent, state, key, mid);
    } else {
      this.setSelectOrHover(ent, state, key, mid);
    }
  }
  /**
   * 根据给定的实体信息，获取与之相关的实体信息数组。
   * @param e - 实体信息对象，包含实体的相关信息。
   * @param entType - 实体类型。
   * */
  getEntByOtherEnt(e: EntityInfo, entType?: EntityPartType[] | EntityPartType) {
    const { dxid = undefined, type, idx } = e;
    const allEnt = this.geometryMgr.findRelatedEntityInfos(dxid, type, idx);
    const tempType = entType ?? this.currentPickType;
    const entTypes = Array.isArray(tempType) ? tempType : [tempType];
    return allEnt.filter((item) => entTypes.includes(item.type));
  }

  release(): void {
    this._entSelect.release();
    this._pickSelect.release();
  }
  cmdExit() {
    if (this.cmdIsCall) {
      this.setCmdPickType(null);
      this.cmdIsCall = false;
      this._pickSelect.unregisterEvents();
      this.exit();
    }
  }
  exit() {
    this._pickSelect.setEntsSelected(false); // 取消之前的选中状态
    // this.enablePick = false;
    this.resetSelectedColor();
    this.release();
  }
  unregisterEvents = () => {
    this._pickSelect.unregisterEvents();
  };
  public registerEvents = () => {
    this._pickSelect.registerEvents();
  };
}
export const pickManager = () => {
  return PickManager.getInstance();
};
